package cn.fayang.ymcc.service.impl;

import cn.fayang.ymcc.constans.SmsCodeConstants;
import cn.fayang.ymcc.constant.CommonConstants;
import cn.fayang.ymcc.constant.YmccExceptionConstant;
import cn.fayang.ymcc.constant.util.AssertUtil;
import cn.fayang.ymcc.domain.Blacklist;
import cn.fayang.ymcc.domain.MessageSms;
import cn.fayang.ymcc.domain.User;
import cn.fayang.ymcc.dto.RedisRegisterDto;
import cn.fayang.ymcc.dto.RegisterDto;
import cn.fayang.ymcc.mapper.BlacklistMapper;
import cn.fayang.ymcc.service.IBlacklistService;
import cn.fayang.ymcc.service.IMessageSmsService;
import cn.fayang.ymcc.service.IVerifyCodeService;
import cn.fayang.ymcc.util.StrUtils;
import cn.fayang.ymcc.util.VerifyCodeUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.security.GeneralSecurityException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import static com.sun.xml.internal.ws.spi.db.BindingContextFactory.LOGGER;

@Service
@Slf4j
public class VerifyCodeServiceImpl extends ServiceImpl<BlacklistMapper, Blacklist> implements IVerifyCodeService {


    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private IMessageSmsService messageSmsService;

    @Autowired
    private SmsCodeConstants smsCodeConstants;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private IBlacklistService blacklistService;


    public Boolean invokeExceededTimes(String key, int days, int count) {
        // 判断在redis中是否有key值
        Boolean redisKey = stringRedisTemplate.hasKey(key);
        if (redisKey) {
            // 获取key所对应的value
            Integer hasKey =Integer.parseInt((String)stringRedisTemplate.opsForValue().get(key));
            if (hasKey >= count) {
                System.out.println(count);
                return false;
            }
            // 对value进行加1操作
            stringRedisTemplate.opsForValue().increment(key,1);
            return true;
        }else {
            // 如果没有key值，对他进行添加到redis中  分钟

            stringRedisTemplate.opsForValue().set(key,"1",days,TimeUnit.MINUTES);
        }
        return true;
    }

    @RequestMapping("hello")

    /*@Value("${register.smscode.interval}")
    private Integer interval;*/

    @Override
    public String imageCode(String key) {


        String code = StrUtils.getComplexRandomString(4);
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.DAYS);
        try {
            return VerifyCodeUtils.VerifyCode(100, 40, code);
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
            return null;
        }



    }





    @Override
    public void smsCode(RegisterDto dto) {
        String smsCode = dto.getSmsCode();
        String mobile = dto.getMobile();

        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String remoteAddr = request.getRemoteAddr();
        Boolean aBoolean = invokeExceededTimes(remoteAddr,1,50);
        String str = "刷接口";
        if (aBoolean) {
            LOGGER.info("可以访问");
        }else {
            LOGGER.info("请勿频繁刷新");
            //接口防刷
            saveBlacklist(mobile,remoteAddr,str);
        }
        AssertUtil.isNull(selectBlackList(mobile),YmccExceptionConstant.COMMON_PHONE_BLICKLIST.getMessage());
        AssertUtil.isNotEmpty(mobile,YmccExceptionConstant.COMMON_PHONE_NO_EMPTY.getMessage());
        AssertUtil.isPhone(mobile,YmccExceptionConstant.COMMON_PHONE_ILLEGAL.getMessage());//手机号不合法
//        二：验证码
        String key = String.format(CommonConstants.REGISTER_PHONE_PRIFIX, mobile);//register:158234234
        Date now = new Date();
//        1.校验手机号是否发送过验证码
        Object o = redisTemplate.opsForValue().get(key);
        String code = null;
        if(o != null){
//        2.从redis拿到了
            RedisRegisterDto registerDto = (RedisRegisterDto) o;
            boolean canSend = (now.getTime() - registerDto.getTime()) / 1000 > smsCodeConstants.getInterval();
            AssertUtil.isTrue(canSend,YmccExceptionConstant.COMMON_SERIOUS.getMessage());

//        2.2 过了重发时间，使用还未过期的码儿
            code = registerDto.getCode();
        }else{
            //        3.拿不到
//        3.1.生成验证码
            code = StrUtils.getRandomString(6);
        }
//        3.2.存储验证码
        //String codeValue = code + ":"+System.currentTimeMillis();
        RedisRegisterDto redisRegisterDto = new RedisRegisterDto(code, now.getTime());
        redisTemplate.opsForValue().set(key,redisRegisterDto,smsCodeConstants.getTimeout(), TimeUnit.SECONDS);
//        3.3.发送验证码短信
        String message = String.format(smsCodeConstants.getSmsmessage(), code);
        log.info(message);
//        3.4.存储发送信息到数据库
        saveMessageSms(now, code, message);
    }

    private Blacklist selectBlackList(String mobile) {
        Wrapper<Blacklist> tWrapper = new EntityWrapper();
        tWrapper.eq("phone",mobile);  // where phone = 123123
        return selectOne(tWrapper);
    }

    private Boolean saveBlacklist(String mobile, String remoteAddr, String str) {
        Blacklist blacklist = new Blacklist();
        blacklist.setPhone(mobile);
        blacklist.setIp(remoteAddr);
        blacklist.setInstro(str);
        return blacklistService.insert(blacklist);

    }


    private void saveMessageSms(Date now, String code,String message) {
        MessageSms messageSms = new MessageSms();
        messageSms.setContent(message);
        messageSms.setSendTime(now);
        messageSms.setTitle(smsCodeConstants.getTitle());
        // 获取请求体 request
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        messageSms.setIp(request.getRemoteAddr());//获取IP地址
        messageSmsService.insert(messageSms);
    }

}

